﻿using System;
using System.Linq;
using ChiWalker.Dynamics;
using ChiWalker.Helpers;
using ChiWalker.Spell;
using ChiWalker.Utilities;
using Styx;
using Styx.Common.Helpers;
using Styx.TreeSharp;
using Styx.WoWInternals.WoWObjects;

namespace ChiWalker.Routines.Priest
{
    internal class Shadow
    {
        private static readonly WaitTimer VtCooldown = new WaitTimer(TimeSpan.FromSeconds(1.5));
        private static readonly WaitTimer SwpCooldown = new WaitTimer(TimeSpan.FromSeconds(1.5));

        private static WoWUnit DotTarget(string missingAura)
        {
            return
                Clusters.NearbyUnitsInCombatWithMe.FirstOrDefault(
                    u => u.InLineOfSight && u.GetAuraTimeLeft(missingAura, true).TotalSeconds <= 2);
        }

        [Behavior(BehaviorType.Combat | BehaviorType.Pull)]
        [Spec(WoWSpec.PriestShadow)]
        [Class(WoWClass.Priest)]
        public static Composite PriestShadow()
        {
            return new PrioritySelector(
                new CastOnSelf(Spell.DespareatePrayer, ret => StyxWoW.Me.HealthPercent <= 50),
                new CastOnSelf(Spell.PowerWordShield,
                    ret => StyxWoW.Me.HealthPercent <= 80 && !StyxWoW.Me.GroupInfo.IsInParty),
                new CastOnSelf(Spell.Dispersion, ret => StyxWoW.Me.ManaPercent <= 50),
                new CastOnSelf(Spell.Shadowform, ret => !StyxWoW.Me.HasAura("Shadowform")),
                new CastOnSelf(Spell.InnerFire, ret => !StyxWoW.Me.HasAura("Inner Fire")),
                Safers.EnsureTarget(),
                new Decorator(ret => StyxWoW.Me.ChanneledCastingSpellId != 15407,
                    WaitFor.WaitForCast()),
                Movement.MoveToLoS(ret => StyxWoW.Me.CurrentTarget),
                Movement.MoveToUnit(ret => StyxWoW.Me.CurrentTarget, ret => 40f),
                Movement.FaceMyTarget(),
                new CastOnMyTarget(Spell.Silence,
                    ret =>
                        StyxWoW.Me.CurrentTarget.CanInterruptCurrentSpellCast &&
                        StyxWoW.Me.CurrentTarget.IsCasting),
                new CastOnMyTarget(Spell.MindSear,
                    ret =>
                        Clusters.GetClusterCount(StyxWoW.Me.CurrentTarget, Clusters.NearbyUnitsInCombatWithMe,
                            ClusterType.Radius, 12f) >= 5),
                new CastOnSelf(Spell.Mindbender),
                new CastOnSelf(Spell.VampiricEmbrace, ret => StyxWoW.Me.HealthPercent <= 60),
                new CastOnMyTarget(Spell.ShadowWordDeath, ret => StyxWoW.Me.CurrentTarget.HealthPercent <= 20),
                new CastOnMyTarget(Spell.MindSpike, ret => StyxWoW.Me.HasAura("Surge of Darkness")),
                new CastOnMyTarget(Spell.Shadowfiend, ret => StyxWoW.Me.ManaPercent <= 90),
                new CastOnUnit(Spell.ShadowWordPain, ret => DotTarget("Shadow Word: Pain"),
                    ret =>
                        SwpCooldown.IsFinished && DotTarget("Shadow Word: Pain") != null && StyxWoW.Me.Combat,
                    ret => SwpCooldown.Reset(), true),
                new CastOnUnit(Spell.VampiricTouch, ret => DotTarget("Vampiric Touch"),
                    ret => VtCooldown.IsFinished && DotTarget("Vampiric Touch") != null,
                    ret => VtCooldown.Reset(), true),
                new CastOnMyTarget(Spell.DevouringPlague,
                    ret => StyxWoW.Me.GetCurrentPower(WoWPowerType.ShadowOrbs) >= 3, null, true),
                new CastOnMyTarget(Spell.ShadowWordPain,
                    ret =>
                        SwpCooldown.IsFinished &&
                        StyxWoW.Me.CurrentTarget.GetAuraTimeLeft("Shadow Word: Pain", true).TotalSeconds <= 2,
                    ret => SwpCooldown.Reset(), true),
                new CastOnMyTarget(Spell.VampiricTouch,
                    ret =>
                        VtCooldown.IsFinished &&
                        StyxWoW.Me.CurrentTarget.GetAuraTimeLeft("Vampiric Touch", true).TotalSeconds <= 2,
                    ret => VtCooldown.Reset(), true),
                new CastOnMyTarget(Spell.MindBlast),
                new CastOnMyTarget(Spell.MindFlay)
                );
        }

        [Behavior(BehaviorType.OutOfCombat)]
        [Spec(WoWSpec.PriestShadow)]
        [Class(WoWClass.Priest)]
        public static Composite ShadowOOC()
        {
            return new PrioritySelector(
                WaitFor.WaitForCast(),
                Group.BuffStam(),
                new CastOnSelf(Spell.Shadowform, ret => !StyxWoW.Me.HasAura("Shadowform")),
                new CastOnSelf(Spell.InnerFire, ret => !StyxWoW.Me.HasAura("Inner Fire"))
                );
        }
    }
}